#ifndef PRISM_MARSHALL_HPP
#define PRISM_MARSHALL_HPP
//=====================================================================
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
//=====================================================================
#include <atma/assert.hpp>
//=====================================================================
#include <prism/frontend/syntactical_analysis/parse.hpp>
//=====================================================================
namespace prism {
//=====================================================================

	namespace marshall
	{
		//=====================================================================
		// the ugly macro code
		//=====================================================================
		#if defined(DEF) || defined(CHILD) || defined(NODE)
			#error 'DEF', 'CHILD', or 'NODE' already defined
		#else
			#define CHILD(num) \
				n->children[num]
			
			#define NODE() \
				n
			
			#define DEF(name, way) \
				inline sooty::const_parseme_ptr_ref name(sooty::const_parseme_ptr_ref n) { return way; } \
				inline sooty::parseme_ptr_ref name(sooty::parseme_ptr_ref n) { return way; }
		#endif
		
		
		//=====================================================================
		//
		//  if you ever wanted an easy way to view how the tree would be flat,
		//  then this file is probably your best bet.
		//
		//=====================================================================
		namespace function
		{
			DEF( name,				CHILD(0) )
			DEF( parameter_list,	CHILD(1) )
			DEF( return_type,		CHILD(2) )
			DEF( body,				CHILD(3) )
		}
		
		namespace function_call
		{
			DEF( name,				CHILD(0) )
			DEF( argument_list,		CHILD(1) )
		}
		
		namespace argument
		{
			DEF( name,				NODE() )
			DEF( type,				NODE() )
		}
		
		namespace return_statement
		{
			DEF( expression,		CHILD(0) )
		}
		
		namespace variable_definition
		{
			DEF( name,				CHILD(0) )
			DEF( type,				CHILD(1) )
			DEF( defvalue,			CHILD(2) )
			inline bool has_defvalue(sooty::const_parseme_ptr_ref N) { return N->children.size() == 3; }
			inline bool is_parameter(sooty::const_parseme_ptr_ref N) { return sooty::parseme_ptr(N->parent)->id == parsid::parameter_list; }
		}
		
		namespace identifier
		{
			DEF( name,					NODE()		)
			DEF( variable_definition,	CHILD(0)	)
		}
		
	}
	
	#undef DEF
	#undef CHILD
	#undef NODE

//=====================================================================
} // namespace prism
//=====================================================================
#endif
//=====================================================================
